import {request} from "express";
import {appendHandler} from "jsdom/lib/jsdom/living/helpers/create-event-accessor";

class Father {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }

    sum() {
        console.log(this.x + this.y);
    }
}

class Son extends Father {
    constructor(x, y) {
        //调用父类构造函数
        //利用super调用父类构造函数  super必须在子类this前调用
        super(x, y);
        this.x = x;
        this.y = y;
    }

    subtract() {
        console.log(this.x - this.y)
    }
}

//实际利用子类父类的构造函数
var son = new Son(1, 2);
son.sum();
son.subtract();
//继承中，子类调用方法，子类有则调用，子类没有找父类同名方法

//let与const---------------------------------------------------------------------------------------------------
// let 声明变量：
// 没有变量提升
//是块级作用域 受{}约束
//不能重复声明
let a = 11;

//const 声明常量：
//没有变量提升
//一旦被声明无法更改
const b = 22;
const c = {
    name: "张"
}
c.name = "李";

//不会污染全局变量
let RegExp = 10;
console.log(RegExp);
console.log(window.RegExp);

//模板字符串------------------------------------------------------------------------------------------
const oBox = document.querySelector('.box');
let id = "a1", name = "孙";
let htmlStr = `<p id=${id}>${name}</p>`;
oBox.innerHTML = htmlStr;

//函数默认值-----------------------------------------------------------------------------------------
function add(a = 10, b = getVal(5)) { //设置默认值
    return a + b;
}

function getVal(val) {
    return val + 5;
}

//函数剩余参数: ...紧跟着的具名参数    -------------------------------------------------
let book = {
    title: '教程书1',
    author: '刘',
    year: '2020'
}

function pick(obj, ...keys) {
    console.log(keys);  /* ['year', 'author'] */
    let result = {};
    for (let i = 0; i < keys.length; i++) {
        result[keys[i]] = obj[keys[i]]
    }
    return result;
}

let bookData = pick(book, 'year', 'author')
console.log(bookData)
//扩展运算符-------------------------------------------------------------------------
//数组最大值：
const arr = [1, 2, 3, 4, 5];
// apply实际把数组分隔
console.log(Math.max.apply(null, arr)) //对象,值

//箭头函数：
let add2 = (a, b) => {
    return a + b;
}
let add3 = val2 => (val2 + 1);
//箭头函数没有this指向，只能通过查找作用域链
//内部this实际取值外层this
//无arguments
//function函数是对象 箭头函数不是对象

//解构赋值-----------------------------------------------------------------------------------
let node = {
    type2: 'a',
    name2: 'b'
}
//多对多赋值 变量名=对象属性名
let {type2, name2} = node;
console.log(type2, name2);
//默认值
let {d, e = 30} = {d: 20};

//数组解构
let arr2 = [1, 2, 3];
let [f, g, h] = arr2;
console.log(f, g, h);

//对象扩展------------------------------------------------------------------------------------------
const name3 = 'li', age2 = 20;
const person = {
    name3,
    age2,
    sayName3() {
        console.log(name3)
    },
    [name3 + '3']: 'liu'
}

//对象比值
console.log(+0 === -0) /* true */
console.log(NaN === NaN) /* false */
console.log(Object.is(NaN, NaN)) /* true */
console.log(isNaN(NaN))/*true */

//对象合并
Object.assign({}, {a: 1})

//Symbol-----------------------------------------------------------------------------------------------
//独一无二的值
//无法进行遍历
const dd = Symbol('ff');
const dd2 = Symbol('ff2');
console.log(dd === dd2); /* false */

let obj2 = {
    [dd]: 'dd1',
    [dd2]: 'dd2'
};
//只能用[] 不用.
console.log(dd); /* Symbol(ff) */
console.log(obj2[dd]); /* dd1 */
//两种遍历方式
console.log(Object.getOwnPropertySymbols(obj2)); /* [Symbol(ff), Symbol(ff2)] */
console.log(Reflect.ownKeys(obj2)) /* [Symbol(ff), Symbol(ff2)] */

//Map Set -------------------------------------------------------------------------------------------------------
//Map 键值对有序列表 键值任意类型
let map = new Map();
map.set('name1', 'zhang');
map.set('name2', 'li');
map.get('name1');
map.size;
let map2 = new Map(
    [
        ['a', '1'],
        ['b', '2']
    ]
);


//Set 无重复值有序数列
let set = new Set();
set.add(1)
set.has(3)
set.delete(2)
set.size
// set.forEach((val,key) => {
//     val = key
//     console.log(val);
//     console.log(key);
// })

// set转数组
let arrSet = [...set];

//Set:
//数列子项无法被释放
// obj = null不生效
// WeakSet；
//不能传入非对象 不可迭代 没有forEach() 没有size
let set2 = new WeakSet(), obj = {};
set2.add(obj)
obj = null;//生效 在weakSet前提下

//Array.from() .of() .copyWithin() .find() .findIndex() .keys() .values() .entries()---------------------------------------------------------------------------------------------
//from() 伪数组转数组
let lis = document.querySelectorAll('li');

let arr4 = Array.from(lis);
console.log(arr4);

//from() 接受第二个参数，对每个元素进行处理
let liContents = Array.from(lis, ele => ele.textContent);
console.log(liContents)

//of() 将一组值，转为数组
Array.of('a', '2', 'kf', '11') /* ['a', '2', 'kf', '11'] */

//copyWithin() 复制替换 索引3后面值替换索引0后面值
let arr5 = [1, 2, 3, 4, 5, 6];
arr5.copyWithin(0, 3, 5) /* [4, 5, 6, 4, 5, 6] */

//find() findIndex()
let arr6 = [1, 2, -10, 40, 52];
arr6.find(n => n < 0) /* -10 */
arr6.findIndex(n => n < 0) /* 2 */

//keys() values() entries() 返回遍历器
for (let index of ['a', 'b'].keys()) {
    console.log(index) /* 0 */ /* 1 */
}
for (let value of ['a', 'b'].values()) {
    console.log(value) /* a */ /* b */
}
for (let index of ['a', 'b'].entries()) {
    console.log(index) /* [0, 'a'] */ /* [1, 'b'] */
}
let letter = ['a1', 'b2', 'c3'];
let it = letter.entries();
console.log(it.next().value) /* [0, 'a'] */  /* [1, 'b'] */ /* [0, 'a1'] */

//includes()
console.log(arr6.includes(2)) /* true */
console.log(arr6.indexOf(2)) /* 1 */

//Iterator迭代器----------------------------------------------------------------------------------------------
// 迭代器是能快捷访问数据的接口
// 迭代器是用于遍历数据结构的指针
const items = ['one', 'two', 'three'];
const ite = items[Symbol.iterator]();
console.log(ite.next())

//generator函数 生成器-----------------------------------------------------------------------------------------
//使用场景：为不具备Iterator接口的对象提供遍历操作
// yield将函数挂起 下面内容不执行等待下次
/*
one
{value: 2, done: false}
two
{value: 3, done: false}
three
{value: undefined, done: true}
*/
function* func(params) {
    console.log('one');
    yield 2;
    console.log('two');
    yield 3;
    console.log('three');
    yield 4;
    console.log('four');

}

let fn = func();
console.log(fn.next());
console.log(fn.next());
console.log(fn.next());


/*
start
JsES6Study.js:285 {value: '2', done: false}
JsES6Study.js:278 one:20
JsES6Study.js:286 {value: '3', done: false}
JsES6Study.js:280 two:30
JsES6Study.js:287 {value: 50, done: true}
 */

//第n次调用第n个yield决定返回值   第n次yield ()内决定第n-1个yield的值
function* add4() {
    console.log('start');
    let x = yield '2';
    console.log('one:' + x);
    let y = yield '3';
    console.log('two:' + y);
    return x + y;
}

const fn2 = add4();
console.log(fn2.next());
console.log(fn2.next(20));
console.log(fn2.next(30));


////使用场景：为不具备Iterator接口的对象提供遍历操作
const obj3 = {
    name: 'li',
    age: 18
}

function* objectEntries(obj) {
    const propKeys = Object.keys(obj3);
    for (const propkey of propKeys) {
        yield [propkey, obj3[propkey]]
    }
}

obj3[Symbol.iterator] = objectEntries;
console.log(obj3); /* {name: 'li', age: 18, Symbol(Symbol.iterator): ƒ} */
/*
name,li
JsES6Study.js:304 age,18
 */
for (let [key, value] of objectEntries(obj3)) {
    console.log(`${key},${value}`)
}

//Generator------------------------------------------------------------------------------
$.ajax({
    url: '',
    method: 'get',
    success(res) {
        console.log(res);
        //继续发送请求
        $.ajax({
            url: '',
            method: 'get',
            success(res1) {
                console.log(re1);
                //继续发送请求
            }
        })
    }
})

function* main() {
    yield
    request('')
}

function request(url) {
    $.ajax({
        url,
        method: 'get',
        success(res) {

        }
    })
}

//Promise-----------------------------------------------------------------------------------------
//相对于容器 保存未来才结束的事件
//各种一步操作可以用同样的方法来处理
//Pending进行 Resolved成功 Rejected失败
//一旦状态改变就不会再变
let pro = new Promise(function (resolve, reject) {
    let res = {
        code: 10,
        data: {
            name: 'aaa'
        }
    }
    setTimeout(() => {
        if (res.code === 10) {
            resolve(res.data);
        } else {
            resolve(res.err);
        }
    }, 1000);
})

pro.then((val) => {
    console.log(val)
}, (err) => {
    console.log(err)
})

//-----缩略为：
function timeOut(ms) {
    return new Promise((resolved, rejected) => {
        setTimeout(() => {
            resolve('hello promise success!!')
        }, ms);
    })
}

timeOut(2000).then((val) => {
    console.log(val)
})
//使用Promise封装ajax-------------------------------------------------------------------------------------------------
const getJSON = function (url) {
    return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open('GET', url);
        xhr.onreadystatechange = handler;
        xhr.responseType = 'json';
        xhr.setRequestHeader('Accept', 'application/json');
        xhr.send();

        function handler() {
            if (this.readyState === 4 && this.status === 200) {
                resolve(this.response);
            } else {
                reject(new Error(this.statusText))
            }

        }
    });
}

getJSON('').then((data) => {
    console.log(data);
}, (error) => {
    console.log(error);
})
getJSON('').then((data) => {
    console.log(data);
}).catch(error => {
    console.log(error);
})
//async---------------------------------------------------------------------------------------------
//异步操作
async function f() {

}

//class类--------------------------------------------------------------------------------------------
class P {

}

class Person extends P {
    constructor(name, age) {
        //写在前
        super();
        this.name = name;
        this.age = age;
    }

    sayName() {
        return this.name;
    }
}

let p1 = new Person('aa', 11);

//通过Object.assign()添加方法
Object.assign(Person.prototype, {
    sayAge() {
        return this.age;
    }
})
//-----------------------------------------------------------------------------------------------
// 规定对外接口
export const aa = 11;
//规定引入内容
import {aa} from 'jsES6Study.js'


